﻿

(function ($) {


    $.fn.validatingForm = function (options) {
        var defaults = {
            formContainer: $(this).selector,
            submitButtonId: "",
            fieldNameGetterPrefix: "span_",
            clearErrorsOnFocus: false,
            clearErrorTipsTrigger: "",
            showSingleError: true,
            summaryTo: "",
            validateOnBlur: false,
            success: function (e) { return true; },
            error: function (e) { return false; }
        }
        var validatorClasses = [
        ".required-field",
        ".email-field",
        ".telphone-field",
        ".phoneNumber-field",
        ".IDCard-field",
        ".selectable-field",
        ".endDate-field", // this validator must be markuped at the EndDate Element
        ".no-Chinese-field",
        ".dateTime-field",
        ".betweenvalue-field",
        ".number-field",
        ".money-field",
        ".score-field"
        ];

        var opts = $.extend(defaults, options);
        
        var _submitButton = $(opts.formContainer).find(".validation-submitbutton:first");
        if (_submitButton != null && _submitButton.length > 0) {
            opts.submitButtonId = "#" + _submitButton.attr("id"); // _btnId;
        }
        else {
            _submitButton = $(opts.submitButtonId).first();
        }
        var fields = "";
        try{
        initializeValidation(opts, fields);
        }catch(e){alert(e);}
        $(_submitButton).click(function () {
            doValidate(opts);
            var all_ok = validatingResult == null || validatingResult.length == 0;
            if (all_ok) {
                return opts.success(opts);
            }
            else {
                opts.error(opts);
                return false;
            }
        });

        var validatingResult = [];
        var __validatorCount = 0;
        function doValidate(opts) {

            resetTips(opts);
            var formContainer = opts.formContainer;
            __validatorCount = validatorClasses.length;
            for (var i = 0; i < __validatorCount; i++) {
                var _validator = validatorClasses[i];
                var _errors = ___validate($(formContainer).find(_validator), _validator, opts);
                if (_errors.length > 0) {
                    validatingResult = validatingResult.concat(_errors);
                }
            }
            buildValidationError(validatingResult, opts, false);
        }

        function buildValidationError(errorsArr, opts, isFromSingle) {
            if (isFromSingle == true) {
                $(errorsArr).each(function (item) {
                    resetSingle(opts, errorsArr[item].id);
                });
            }
            if (errorsArr != null && errorsArr.length > 0) {
                var length = errorsArr.length;
                if (opts.showSingleError == true) { // determine whether show error for each element.
                    for (var i = 0; i < length; i++) {
                        var _id = errorsArr[i].id;
                        var tipsContainer = "#tipsFor_" + _id;
                        var msg = errorsArr[i].errorMsg;
                        $(tipsContainer).append('<li forid="' + _id + '"><label for="' + _id + '">' + msg + '</label></li>');
                    }
                } var summaryContainer = $(opts.summaryTo);
                if (opts.summaryTo && summaryContainer != null && summaryContainer.length > 0) {
                    if (isFromSingle == false) {
                        var temp = "";
                        for (var i = 0; i < length; i++) {
                            var msg = errorsArr[i].errorMsg;
                            var _id = errorsArr[i].id;
                            var fieldname = errorsArr[i].fieldName;
                            temp += '<li forid="' + _id + '"><label for="' + _id + '">' + fieldname + msg.replace(fieldname, "") + '</label></li>';
                        }
                        var forSummary = errorTipsContainerBuilder(opts.summaryTo.replace("#", ""), temp);
                        $(opts.summaryTo).first().html(forSummary);
                    }
                    else {

                        var temp = "";
                        for (var i = 0; i < length; i++) {
                            var msg = errorsArr[i].errorMsg;
                            var _id = errorsArr[i].id;
                            var fieldname = errorsArr[i].fieldName;
                            temp += '<li forid="' + _id + '"><label for="' + _id + '">' + fieldname + msg.replace(fieldname, "") + '</label></li>';
                        }
                        $(opts.summaryTo + " ul.validation-error:first").append(temp);
                    }
                }
            }
        }

        function resetTips(opts) {
            validatingResult = new Array();
            var container = opts.formContainer;
            $(container + "," + opts.summaryTo).find("ul.validation-error").html("");
        }
        function resetSingle(opts, _id) {
            var tipsid = "#tipsFor_" + _id;
            $(tipsid).html("");
            var length = $(opts.summaryTo).find('ul.validation-error li[forid="' + _id + '"]');
            if (length.length > 0)
                length.remove();
        }

        function ___validate(items, validator, opts) {
            var tempArr = [];
            items.each(function (item) {
                var _id = $(this).attr("id");
                var _fileName = $(this).attr("fieldName") || "";
                if (_fileName == "") {
                    _fileName = $("#" + opts.fieldNameGetterPrefix + _id).text();
                    $(this).attr("fieldName", _fileName);
                }
                var _val = $(this).val();
                var _temp = validateValidator(validator, _id, _val, _fileName);
                if (_temp.isAvailable == false) {
                    tempArr.push(_temp);
                }
            });
            return tempArr;
        }


        function initializeValidation(opts) {

            __validatorCount = validatorClasses.length;
            fields = "";
            fields = validatorClasses.join(","); // fields.substring(0, fields.length - 1); 
            var formContainer = opts.formContainer;
//            $(formContainer).find(fields).each(function (item) {
//                if ($(this).next("div.validation-error-container:first").length <= 0) {
//                    var _id = $(this).attr("id");
//                    $(errorTipsContainerBuilder(_id, "")).insertAfter("#" + _id);
//                }
//
//            });
            if (opts.clearErrorsOnFocus == true) {
                $(formContainer).find(fields).focus(function () {
                    var _id = $(this).attr("id");
                    resetSingle(opts, _id);
                });
            }
            if (opts.validateOnBlur == true) {
                $(formContainer).find(fields).blur(function () {
                    var _id = $(this).attr("id");
                    var _fields = $(this).attr("validators");
                    if (_fields == undefined || _fields == "") {
                        _fields = getValidators($(this).attr("class"));
                        $(this).attr("validators", _fields);
                    }
                    var tempError = [];
                    _fields = _fields.split(",");
                    var _obj = $(this);
                    $(_fields).each(function (index) {
                        var __ = ___validate(_obj, _fields[index], opts);
                        if (__.length > 0) {
                            tempError = tempError.concat(__);
                        }
                    });
                    buildValidationError(tempError, opts, true);
                });
            }
            if (opts.clearErrorTipsTrigger != "" && $(opts.clearErrorTipsTrigger).length > 0) {
                $(opts.clearErrorTipsTrigger).click(function () {
                    resetTips(opts);
                });
            }
            if (opts.summaryTo != "") {
                $(opts.summaryTo).append(errorTipsContainerBuilder(opts.summaryTo.replace("#", ""), ""));
            }
        }

        function getValidators(classes) {
            var arr = classes.split(' ');
            var _result = [];
            $(arr).each(function (index) {
                var _vl = "." + arr[index];
                if (validatorClasses.indexOf(_vl) > -1) {
                    _result.push(_vl);
                }
            });
            return _result.join(",");
        }

        function errorTipsContainerBuilder(_id, _def) {
            return '<div class="validation-error-container"><ul id="tipsFor_' + _id + '" class="validation-error">' + _def + '</ul></div>';
        }



        function validateValidator(validator, id, val, fieldName) {
            var result = false;
            var __id = "#" + id;
            var _defMsg = "";
            val = $.trim(val);
            
            
            switch (validator) {
                case validatorClasses[0]: //".required-field":
                    result = requireValidate(val);
                    _defMsg = fieldName + " 不能为空。";
                    break;
                case validatorClasses[1]: //".email-field":
                    result = emailValidate(val);
                    _defMsg = " 输入的必须是有效的 Email 格式。";
                    break;
                case validatorClasses[2]: //".telphone-field":
                    result = telphoneValidate(val);
                    _defMsg = " 输入的必须是有效的手机号码。";
                    break;
                case validatorClasses[3]: //".phoneNumber-field":
                    result = phoneNumberValidate(val);
                    _defMsg = " 输入的必须是有效的电话号码。";
                    break;
                case validatorClasses[4]: //".IDCard-field":
                    result = IDValidate(val);
                    _defMsg = " 输入的必须是有效的身份证号码。";
                    break;
                case validatorClasses[5]: //".selectable-field": 
                    result = selectValidate(__id, val);
                    _defMsg = $(__id).attr("emptyValueMsg") || "请至少选择一项有效值。";
                    break;
                case validatorClasses[6]: //
                    _defMsg = validateDateTimeMustBeLarger(__id, val, fieldName);
                    result = _defMsg.length == 0;
                    break;
                case validatorClasses[7]:
                    _defMsg = " 只能包括英文字母、数字和下划线。";
                    result = notChineseCharacters(val);
                    break;
                case validatorClasses[8]:
                    _defMsg = validateDateTime(__id, val, fieldName);
                    result = _defMsg.length == 0;
                    break;
                case validatorClasses[9]:
                	_defMsg =  validateBetweenValue(__id,val,fieldName);
                	result = _defMsg.length == 0;
                	break;
                case validatorClasses[10]:
                	_defMsg =  " 只能是数字。";
                	result = validateNumber(__id,val,fieldName);
                	break;
                case validatorClasses[11]:
                	_defMsg =  " 输入的必须是有效的金额(两位小数)。";
                	result = validateMoney(__id,val,fieldName);
                	break;
                case validatorClasses[12]:
                	_defMsg =  " 输入的必须是有效的成绩(两位小数)。";
                	result = validateScore(__id,val,fieldName);
                	break;
            }
            return { isAvailable: result, id: id, fieldName: fieldName, errorMsg: _defMsg };
        }


        $.fn.validatingForm.BlurErrorTips = function (Selector) {
            resetTips({ formContainer: Selector });
        }
    };
    
    
    function validateBetweenValue(id,val,fieldName)
    {
    	var obj = $(id);
    	var max = obj.attr("max")||"";
    	var min = obj.attr("min");
    	
    	max = parseFloat(max);
    	min = parseFloat(min);
    	val = parseFloat(val);
    	if(val<min || val>max)
    	{
    		return ""+" 必须是大于 "+ min +" 小于 "+ max +" 的值。";
    	}
    	return "";
    	
    }

    function validateDateTime(id, val, field) {
        var obj = $(id);

        var than = obj.attr("than");
        var xtype = obj.attr("xtype") || "date";
        var d1_string, d1_Date, d2_string, d2_Date, thanFieldName;

        if (startWith(than, "#")) {
            var _thanObj = $(than);
            d1_string = getText(_thanObj);
            thanFieldName = _thanObj.attr("fieldName") || d1_string;
        } else if (than == "now") {
            d1_string = getCurrentDateTime("-", true);
            thanFieldName = "当前时间";
        } else {
            d1_string = than;
            thanFieldName = d1_string;
        }
        d1_Date = isDateTime(d1_string);
        d2_Date = isDateTime(val);
        if (isNaN(d2_Date)) {
            return " 不是有效的日期时间。";
        } else if (isNaN(d1_Date)) {
            return " 不是有效的日期时间。";
        } else {
            if (d1_Date > d2_Date) {
                return field + "必须大于" + thanFieldName + "。";
            }

            var beyondInfo = obj.attr("beyond") || "";
            if (beyondInfo != "") {
                beyondInfo = beyondInfo.split(";") || ["", "now", "1,0,0"];
                var op = beyondInfo[0];
                var from = beyondInfo[1] || "";
                var __temp = from == "now" ? getCurrentDateTime("-", true) : "";

                var _fromDate = from == "now" ? isDateTime(__temp) : getDateFromString(from);
                var byDateTime = getDateFromString(beyondInfo[2]);
                //                alert($.toJSON(byDateTime));
                //                alert("from" + _fromDate);
                var y = m = d = 0;
                if (op == "between") {
                    y = _fromDate.getFullYear() + byDateTime.year;
                    m = _fromDate.getMonth() + 1 + byDateTime.month;
                    d = _fromDate.getDate() + byDateTime.day;
                    var key = y + "-" + m + "-" + d;
                    var __beyondDateTime = isDateTime(y + "-" + m + "-" + d);
                    if (d2_Date > __beyondDateTime) {
                        return "必须在 " + __temp + " ~ " + key + " 之间。";
                    } else
                        return "";
                }
            }
            return "";
        }
    }


    function getDateFromString(str) {
        var __d = str.split(",");
        var _fromDate = "";
        if (__d.length == 0 || __d == undefined) return { year: 1, month: 0, day: 0 };
        var y = __d[0] || 0;
        var m = __d[1] || 0;
        var d = __d[2] || 0;
        return { year: parseFloat(y), month: parseFloat(m), day: parseFloat(d) };
    }

    function isDateTime(val) {
        if (val == "now")
            return new Date(getCurrentDateTime("-", true));
        else
            return new Date(val.replace(/\-/g, "\/"));
    }

    function getText(obj) {
        //var tagName = obj.attr("tagName");
        return obj.val();

    }
    

    function validateDateTimeMustBeLarger(id, val, field) {
        var obj = $(id);
        var result = "";
        var temp = "起始时间";

        var d1 = null;
        var d2 = new Date(val.replace(/\-/g, "\/"));

        var startTime = obj.attr("startDate") || "";
        var needLargerThanNow = obj.attr("thannow");

        if (startWith(startTime, "#")) {
            startTime = $(startTime).val();
            d1 = new Date(startTime.replace(/\-/g, "\/"));
        } else {
            temp = startTime;
            d1 = new Date(startTime.replace(/\-/g, "\/"));
        }

        if (d1 > d2) {
            result = "结束时间必须在 " + temp + " 之后!";
        }
        if (needLargerThanNow == "true") {
            d2 = new Date(getCurrentDateTime("-", true).replace(/\-/g, "\/"));
            if (d1 < d2) {
                if (result.length > 0) { result += "<br/>"; }
                result += "起始时间必须大于当前时间!";
            }
        }
        return result;
    }

    function getCurrentDateTime(spl, needTime) {
        var now = new Date();
        var year = now.getFullYear();
        var month = now.getMonth() + 1;
        var day = now.getDate();
        var result = "";
        if (month < 10) {
            result = year + spl + "0" + month + spl + day;
        }
        else { result = year + spl + month + spl + day; }
        if (needTime) {
            result = result + " " + now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds();
        } else
            result = "";
        return result;
    }

    function selectValidate(id, val) {
        var _emptyForValidate = $(id).attr("emptyValueForValidate") || "-1";
        return (val != _emptyForValidate);
    }
    function requireValidate(val) {
        return val.length != 0;
    }
    function emailValidate(val) {
        var reg = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$/;
        return reg.test(val);
    }
    function phoneNumberValidate(val) {
        return true;
    }
    function telphoneValidate(val) {
        var reg = /^(1[0-9][0-9]|15[0|2|3|5|6|7|8|9]|18[6|8|9])\d{8}$/;
        return reg.test(val);
    }

    function IDValidate(val) {
        return (/(^\d{15}$)|(^\d{17}([0-9]|X)$)/.test(val));
    }

    function validateNumber(id,val,fieldName){
    	var reg = /^[0-9]*$/;
    	return reg.test(val);
    }
    
    function validateMoney(id,val,fieldName){
    	var reg = /^[0-9]+(.[0-9]{1,2})?$/;
    	return reg.test(val);
    }
    
    function validateScore(id,val,fieldName){
    	var reg = /^[0-9]+(.[0-9]{1,2})?$/;
    	return reg.test(val);
    }

    function notChineseCharacters(val) {
        return (/^[a-zA-Z0-9_]{1,}$/.test(val));
    }



    //----Extensions Methods ----------------------------------------------//

    function startWith(str, word) {
        if (word == null || word == "" || str.length == 0 || word.length > str.length)
            return false;
        if (str.substring(0, word.length) == word)
            return true;
        else
            return false;
        return true;
    }

    function endWith(str, word) {
        if (word == null || word == "" || str.length == 0 || word.length > str.length)
            return false;
        if (str.substring(str.length - word.length) == word)
            return true;
        else
            return false;
        return true;
    }
    $(function () {
        Array.prototype.indexOf = function (k) {
            var len = this.length;
            for (i = 0; i < len; i++) {
                if (this[i] == k)
                { return i; }
            } return -1;
        };
    });
    //----------------------end------------------//

})(jQuery);

